Atributo: pack_mode
El pragma define cómo se empaqueta una estructura de datos durante la asignación. El atributo debe insertarse sobre la estructura de datos y afecta el empaque de toda la estructura.
Sintaxis:
{attribute 'pack_mode' := ' <pack mode value> '}
Insertar ubicación: encima de la declaración de la estructura de datos
<pack mode value>
<valor del modo de paquete> | Método de embalaje asociado | Descripción |
---|---|---|
0 | Alineado | Todas las variables se asignan a direcciones de bytes. No hay lagunas de memoria. |
1 | 1 byte alineado | |
2 | alineado con 2 bytes | . Existen
|
4 | alineado con 4 bytes | . Existen
|
8 | alineado con 8 bytes | . Existen
|
Sugerencia
Dependiendo de la estructura, puede que no haya diferencia en el mapeo de memoria de los modos individuales. Por ejemplo, la distribución de memoria de una estructura con el {attribute 'pack mode' := '4'}
el pragma puede corresponder al de {attribute 'pack mode' := '8'}
.
Sugerencia
matrices de estructuras
Si las estructuras se combinan en matrices, se agregan bytes al final de la estructura para alinear la siguiente estructura.
Importante
Si el Diseño de compatibilidad se selecciona la opción en la configuración del símbolo y al mismo tiempo el atributo 'pack_mode'
se usa en el código, entonces pueden ocurrir problemas debido a una desalineación involuntaria de la memoria.
Ejemplo 1
{attribute 'pack_mode' := '1'} TYPE myStruct: STRUCT Enable: BOOL; Counter: INT; MaxSize: BOOL; MaxSizeReached: BOOL; END_STRUCT END_TYPE
El rango de memoria para una variable del tipo de datos myStruct
se asigna "alineado". Si la dirección de almacenamiento de su componente Enable
es 0x0100
, por ejemplo, entonces el componente Counter
sigue en la dirección 0x0101
, MaxSize
en la dirección 0x0103
y MaxSizeReached
en la dirección 0x0104
. En el caso de 'pack_mode':=2
, Counter
estaría en 0x0102
, MaxSize
a 0x0104
y MaxSizeReached
a 0x0105
.
Ejemplo 2
STRUCT Var1 : BOOL := 16#01; Var2 : BYTE := 16#11; Var3 : WORD := 16#22; Var4 : BYTE := 16#44; Var5 : DWORD := 16#88776655; Var6 : BYTE := 16#99; Var7 : BYTE := 16#AA; Var8 : DWORD := 16#AA; END_TYPE
pack_mode = 8 | pack_mode = 0 | pack_mode = 1 | pack_mode = 2 | pack_mode = 4 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Variable | Valor | Variable | Valor | Variable | Valor | Variable | Valor | Variable | Valor | |
0 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
|
|
|
3 | … |
| … |
| … |
| … |
| … |
|
4 |
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
| ||||||
6 | … |
| … |
|
|
| ||||
7 | … |
| … |
| … |
| ||||
8 |
|
| … |
| … |
| … |
|
|
|
9 | … |
|
|
|
|
| … |
| … |
|
10 | … |
|
|
|
|
|
|
| … |
|
11 | … |
|
|
|
|
|
|
| … |
|
12 |
|
| … |
| … |
|
|
|
|
|
13 |
|
| … |
| … |
| … |
|
|
|
14 | … |
| … |
| … |
| ||||
15 | … |
| ||||||||
16 |
|
|
|
| ||||||
17 | … |
| … |
| ||||||
18 | … |
| … |
| ||||||
19 | … |
| … |
| ||||||
20 | ||||||||||
21 | ||||||||||
22 | ||||||||||
23 | ||||||||||
24 | ||||||||||
25 | ||||||||||
26 | ||||||||||
27 | ||||||||||
28 | ||||||||||
29 | ||||||||||
30 | ||||||||||
31 |
Ejemplo 3
STRUCT Var1 : BYTE := 16#01; Var2 : LWORD := 16#11; Var3 : BYTE := 16#22; Var4 : BYTE := 16#44; Var5 : DWORD := 16#88776655; Var6 : BYTE := 16#99; Var7 : BYTE := 16#AA; Var8 : WORD := 16#AA; END_TYPE
pack_mode = 8 | pack_mode = 0 | pack_mode = 1 | pack_mode = 2 | pack_mode = 4 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Variable | Valor | Variable | Valor | Variable | Valor | Variable | Valor | Variable | Valor | |
0 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
| ||||||
2 | … |
| … |
|
|
| ||||
3 | … |
| … |
| … |
| ||||
4 | … |
| … |
| … |
|
|
| ||
5 | … |
| … |
| … |
| … |
| ||
6 | … |
| … |
| … |
| … |
| ||
7 | … |
| … |
| … |
| … |
| ||
8 |
|
| … |
| … |
| … |
| … |
|
9 | … |
|
|
|
|
| … |
| … |
|
10 | … |
|
|
|
|
|
|
| … |
|
11 | … |
|
|
|
|
|
|
| … |
|
12 | … |
| … |
| … |
|
|
|
|
|
13 | … |
| … |
| … |
| … |
|
|
|
14 | … |
| … |
| … |
| … |
| ||
15 | … |
|
|
|
|
| … |
| ||
16 |
|
|
|
|
|
|
|
|
|
|
17 |
|
|
|
|
|
|
|
| … |
|
18 | … |
| … |
|
|
| … |
| ||
19 | … |
| … |
| ||||||
20 |
|
|
|
| ||||||
21 | … |
|
|
| ||||||
22 | … |
|
|
| ||||||
23 | … |
| … |
| ||||||
24 |
|
| ||||||||
25 |
|
| ||||||||
26 |
|
| ||||||||
27 | … |
| ||||||||
28 | ||||||||||
29 | ||||||||||
30 | ||||||||||
31 |
Comportamiento sin 'pack-mode'
Si 'pack-mode'
no se utiliza, el compilador suele utilizar el modo de paquete 4 u 8, según la descripción del dispositivo. En cada caso, se utiliza un modo de paquete que es particularmente beneficioso para el procesador para que se pueda realizar el acceso a la memoria. Esto también se denomina alineación natural o alineación natural de datos.
Efectos negativos al usar 'pack-mode'
El acceso a la memoria no alineado puede ser el resultado del uso del atributo 'pack_mode'
. Esto significa, por ejemplo, que un tipo de datos con un tamaño de 4 bytes se encuentra en una dirección que no es divisible por 4. Normalmente, en un sistema de 32 bits, un tipo de datos de 32 bits se puede leer y escribir con un acceso único a la memoria. En algunas plataformas, por ejemplo en plataformas ARM, esto es posible solo cuando este valor está alineado en la memoria. En otras plataformas, puede ser que el acceso sea posible pero se realice mucho más lento.
{attribute 'pack_mode':=1} TYPE DUT STRUCT by1 : BYTE; dw1 : DWORD; END_STRUCT END_TYPE
En una plataforma ARM, el valor dw1
no se puede leer con un solo acceso. Cuando se intenta acceder a este elemento directamente, el procesador ARM generará una excepción.
Suposición: Se realiza el siguiente acceso de lectura: dwTest := dut1.dw1;
Para este acceso a la DWORD dw1
, se requieren cuatro accesos a la memoria porque cada byte se lee, desplaza y separa individualmente. El flujo es algo similar al del siguiente ejemplo en el que un DWORD
se genera a partir de una matriz de cuatro bytes:
dwHelp := bytes[0]; dwResult := dwHelp; dwHelp := bytes[1]; dwHelp := SHL(dwHelp, 8); dwResult := dwResult OR dwHelp; dwHelp := bytes[2]; dwHelp := SHL(dwHelp, 16); dwResult := dwResult OR dwHelp; dwHelp := bytes[3]; dwHelp := SHL(dwHelp, 24); dwResult := dwResult OR dwHelp;
Obviamente, este tipo de acceso es mucho más lento que el acceso a un DWORD
, que se alinea adecuadamente en la memoria.
pdw := ADR(dut1.dw1); dwTest := pdw^;
Sin embargo, el compilador no generará el acceso del ejemplo cuando se acceda a este tipo de miembro por medio de un puntero. Esto significa que el siguiente código genera una excepción en una plataforma ARM.
pdw := ADR(dut1.dw1); dwTest := pdw^;
Por motivos de rendimiento, debe evitar trabajar con estructuras que no estén alineadas de forma natural.
Una estructura empaquetada no debe contener una estructura no empaquetada.